﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using Web.Models;

namespace Web.Controllers
{
    [Authorize]
    public class ReservationsController : Controller
    {
        private static readonly string[] DateTimeFormats = { "dd/MM/yyyy HH:mm", "MM/dd/yyyy HH:mm" };
        private const string DateTimeFormatJson = "yyyyMMddHHmmss";

        private readonly ReservingRoomContext _db = new ReservingRoomContext();

        //
        // GET: /Reservations/
        [AllowAnonymous]
        public ActionResult Index()
        {
            var reservations = _db.Reservations.ToList();
            foreach (var res in reservations)
                res.Room = _db.Rooms.Find(res.RoomId);

            return View(reservations);
        }

        //
        // GET: /Reservations/Details/5
        [AllowAnonymous]
        public ActionResult Details(int id = 0)
        {
            Reservation reservation = _db.Reservations.Find(id);
            if (reservation == null)
            {
                return HttpNotFound();
            }
            return View(reservation);
        }

        //
        // GET: /Reservations/Create
        public ActionResult Create()
        {
            var rooms = new List<SelectListItem>();

            foreach (var room in _db.Rooms)
            {
                rooms.Add(new SelectListItem
                {
                    Text = room.Name,
                    Value = room.Id.ToString()
                });
            }

            ViewBag.Rooms = rooms;
            return View();
        }

        //
        // POST: /Reservations/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Reservation reservation)
        {
            var rooms = new List<SelectListItem>();

            foreach (var room in _db.Rooms)
            {
                rooms.Add(new SelectListItem
                {
                    Text = room.Name,
                    Value = room.Id.ToString()
                });
            }

            ViewBag.Rooms = rooms;

            string date = Request.Form["txtDate"].Trim();
            string start = Request.Form["txtBegin"].Trim();
            string end = Request.Form["txtEnd"].Trim();

            string dtBeginStr = date + " " + start;
            string dtEndStr = date + " " + end;

            DateTime dtBegin;
            if (!DateTime.TryParseExact(dtBeginStr, DateTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dtBegin))
            {
                ModelState.AddModelError(string.Empty, "Error parsing the start date.");
                return View(reservation);
            }

            DateTime dtEnd;
            if (!DateTime.TryParseExact(dtEndStr, DateTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dtEnd))
            {
                ModelState.AddModelError(string.Empty, "Error parsing the end date.");
                return View(reservation);
            }

            if (dtBegin >= dtEnd)
                ModelState.AddModelError(string.Empty, "End time must be after start time.");

            reservation.Begin = dtBegin;
            reservation.End = dtEnd;
            reservation.Created = DateTime.Now;

            if (ModelState.IsValid)
            {
                var existentReservations = _db.Reservations.Where(x =>
                    x.RoomId == reservation.RoomId && (dtBegin > x.Begin || dtEnd < x.End));

                if (existentReservations.Any())
                {
                    var res = existentReservations.First();
                    ModelState.AddModelError(string.Empty,
                        string.Format("There is an reservation in the specified date range for the selected room. " +
                                      "Reservation #{0} - Title: {1} - Date: {2} - Start: {3} - End: {4}.",
                                      res.Id, res.Title, res.Begin.ToString("MM/dd/yyy"), res.Begin.ToString("HH:mm"), res.End.ToString("HH:mm")));
                    return View(reservation);
                }

                var userInfo = _db.UserInfos.First(x => x.UserName == User.Identity.Name);
                reservation.UserInfoId = userInfo.Id;

                _db.Reservations.Add(reservation);
                _db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(reservation);
        }

        //
        // GET: /Reservations/Delete/5
        public ActionResult Delete(int id = 0)
        {
            Reservation reservation = _db.Reservations.Find(id);
            if (reservation == null)
            {
                return HttpNotFound();
            }
            return View(reservation);
        }

        //
        // POST: /Reservations/Delete/5

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Reservation reservation = _db.Reservations.Find(id);
            _db.Reservations.Remove(reservation);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        [AllowAnonymous]
        public JsonResult GetAll(int? days)
        {
            var result = new List<dynamic>();

            var topDate = DateTime.Today.AddMonths(1);
            if (days.HasValue)
                topDate = DateTime.Today.AddDays(1);

            foreach (var room in _db.Rooms.ToList())
            {
                var reservations = new List<dynamic>();

                foreach (var res in _db.Reservations.Where(
                    x => x.RoomId == room.Id
                        && x.Begin > DateTime.Now
                        && x.End < topDate).ToList())
                {
                    var userInfo = _db.UserInfos.Find(res.UserInfoId);

                    reservations.Add(new
                    {
                        id = res.Id,
                        description = res.Title,
                        begin = res.Begin.ToString(DateTimeFormatJson),
                        end = res.End.ToString(DateTimeFormatJson),
                        created = res.Created.ToString(DateTimeFormatJson),
                        user = new
                        {
                            id = userInfo.Id,
                            name = userInfo.FullName,
                            phone_number = userInfo.PhoneNumber,
                            email = userInfo.Email
                        }
                    });
                }

                dynamic r = new
                {
                    id = room.Id,
                    name = room.Name,
                    description = room.Description,
                    color_id = (int) room.Color,
                    reservations = reservations
                };

                result.Add(r);
            }

            return Json(result, JsonRequestBehavior.AllowGet);
        }

        protected override void Dispose(bool disposing)
        {
            _db.Dispose();
            base.Dispose(disposing);
        }
    }
}